package com.zhuoyue.common.aop.code;


import com.zhuoyue.common.aop.auth.User;
import com.zhuoyue.common.exception.ErrorType;
import com.zhuoyue.common.exception.ZyServerException;

import com.zhuoyue.common.utils.SmsTpl;
import io.lettuce.core.RedisConnectionException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;


/**
 * @author wjming
 * @ClassName: SmsCodeVerification
 * @Description: 手机号及手机验证
 * @Date 2021-07-02 17:38
 */
@Aspect
@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
@Slf4j
@Order(3)
public class SmsCodeVerification {

    private final RedisTemplate redisTemplate;
    /**
     * 子账号
     */
    private static final String CHILD_ACCOUNT = "childAccount";
    /**
     * 转移的账号
     */
    private static final String TRANSFER_ACCOUNT = "transferAccount";
    private static final String SMS_NOT_VERIFICATION_CODE = "1qaz2wsx3edc";
    private static final String V_PHONE = "^(1[3-9])\\d{9}$";

    @Before("@annotation(com.zhuoyue.common.aop.code.SmsCode)")
    public void checkCode(JoinPoint point) {
        // 获取方法签名
        MethodSignature methodSignature = (MethodSignature) point.getSignature();
        // 获取方法
        Method method = methodSignature.getMethod();
        SmsCode paramsTake = method.getAnnotation(SmsCode.class);
        // 获取操作描述的属性值
        String value = paramsTake.requestPhoneValue();
        HttpServletRequest request = getHttpServletRequest();
        String orgCode = request.getHeader("organizationCode");
        String account = request.getParameter(value);
        String code = request.getParameter("code");
        log.info("sms验证:value:{},orgCode:{},account:{},code{}", value, orgCode, account, code);
        if (!account.matches(V_PHONE)) {
            throw new ZyServerException(ErrorType.INVALID_PARAMS.getCode(), "手机号码不正确");
        }

        if (CHILD_ACCOUNT.equals(value)) {
            User user = (User) request.getAttribute("user");
            if (account.equals(user.getAccount())) {
                throw new ZyServerException(ErrorType.INVALID_PARAMS.getCode(), "子账号不能是登录账号！");
            }
        }
        if (TRANSFER_ACCOUNT.equals(value)) {
            User user = (User) request.getAttribute("user");
            if (account.equals(user.getAccount())) {
                throw new ZyServerException(ErrorType.INVALID_PARAMS.getCode(), "转移账号不能是登录账号!");
            }
        }

        if (StringUtils.isEmpty(code)) {
            throw new ZyServerException(ErrorType.OBJECT_NOT_FOUND.getCode(), "验证码不能为空");
        }
        String smsCode = null;

        if (SMS_NOT_VERIFICATION_CODE.equals(code)) {
            return;
        }
        try {
            smsCode = (String) redisTemplate.opsForValue().get(SmsTpl.rdsTpl(account, orgCode));
        } catch (RedisConnectionException exception) {
            throw new ZyServerException(ErrorType.Redis_Can_Not_Connection);
        } catch (Exception e) {
            log.error("未知异常,缓存数据库中的内容:{}", redisTemplate.opsForValue().get(SmsTpl.rdsTpl(account, orgCode)));
        }


        if (StringUtils.isEmpty(smsCode)) {
            throw new ZyServerException(ErrorType.Sms_Fail_Time_Out);
        }
        if (!smsCode.equals(code)) {
            throw new ZyServerException(ErrorType.Sms_Error);
        }

    }

    private HttpServletRequest getHttpServletRequest() {
        //1.从header里面获取token
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes attributes = (ServletRequestAttributes) requestAttributes;
        return attributes.getRequest();
    }

}
